/*
The surface-physics project: http://code.google.com/p/surface-physics/
Adds real world physics based on the Bullet physics engine, to bases in the Orbiter space
flight simulation software.

Written by Abhijit Nandy
License : Apache License 2.0


Bump_MSHImporter.cpp

Defines the member functions of the Bump_MSHImporter class


*/

#include "orbitersdk.h"
#include "Bump_MSHImporter.h"


//Debugging
extern char boutput[1000];



/**
 * Constructor for class, doesn't create MSH here
 */
Bump_MSHImporter::Bump_MSHImporter()
{
	rbMSH = NULL;
	collShpMSH = NULL;
	m_indexVertexArrays = NULL;

	vertices = NULL;
	indices = NULL;

	strcpy(fileName, "No MSH defined");

}


/**
 * Destructor, frees memory before destruction
 */
Bump_MSHImporter::~Bump_MSHImporter()
{

	if(vertices)
		delete[] vertices;

	if(indices)
		delete[] indices;

	sprintf(boutput, "Bump_MSHImporter::~Bump_MSHImporter: The MSH \"%s\" vertices & indices freed.",
					fileName);
	oapiWriteLog(boutput);

}



/**
 * Should remove the MSH rigid body, not yet implemented, destructor is good enough
 */
int
Bump_MSHImporter::removeMSH(void)
{
	return 0;
}


/**
 * Adds an Orbiter .msh format mesh to the physics world by reading it from a .msh file
 * Converts the triangle list in .msh -> btBvhTriangleMeshShape
 *
 * Makes a static body, not dynamic
 *
 */
int
Bump_MSHImporter::addMSH(char *fileName, btVector3& offset)
{

	strcpy(this->fileName, fileName);

	int i, g, numGroups = 0, materialIndex=0, textureIndex=0;
	int *nv, *nt;
	float x, y, z, nx, ny, nz;
	char buffer[50], label[50];
	FILE* fp;
	int **mshIndicesList;
	btVector3 **mshVerticesList;
	int totalVertices = 0, totalIndices = 0;

	//create a triangle-mesh
	int vertStride = sizeof(btVector3);
	int indexStride = 3*sizeof(int);
	const float TRIANGLE_SIZE=5.f;

	printf("\n-------Reading msh file------\n");

	fopen_s(&fp, fileName,"r");
	if(fp == NULL){
		sprintf(boutput, "Bump_MSHImporter::addMSH: ERROR : The MSH file \"%s\" could not be opened. Is it being held by another application ?",
				fileName);
		oapiWriteLog(boutput);
		return 1;
	}

	fscanf_s(fp, "MSHX1\n");
	fscanf_s(fp, "GROUPS %d\n", &numGroups);
	printf("Number of groups = %d\n", numGroups);
	mshVerticesList = new btVector3*[numGroups];
	mshIndicesList  = new int*[numGroups];
	nv  = new int[numGroups];
	nt  = new int[numGroups];

	//Read in the vertices of all groups
	for(g=0; g<numGroups; g++){
		fscanf_s(fp, "LABEL ", buffer);
		fgets(label, 49, fp);
		fscanf_s(fp, "MATERIAL %d\n", &materialIndex);
		fscanf_s(fp, "TEXTURE %d\n", &textureIndex);
		fscanf_s(fp, "GEOM %d %d ;", &nv[g], &nt[g]);
		fgets(buffer, 49, fp);
		printf("------------Group = %d(Ignoring normals, materials, textures)-------------\n", g);
		printf("Label = %s", label);
		printf("Material Index = %d\n", materialIndex);
		printf("Texture Index = %d\n", textureIndex);
		printf("Number of vertices=%d, Number of Triangles=%d\n", nv[g], nt[g]);

		//Read in the vertices & normals for the current group in separate arrays
		mshVerticesList[g] = new btVector3[nv[g]];
		for(i=0; i<nv[g]; i++){
			fscanf_s(fp, "%f %f %f %f %f %f\n", &x,  &y,  &z, &nx, &ny, &nz);
			mshVerticesList[g][i].setValue(x, y, z);
		}

		//Read in the triangle indices for the current group in separate arrays BUT
		//offset the current group's indices by previously read total indices to have uniform triangle information
		mshIndicesList[g] = new int[nt[g]*3];
		for(i=0; i<nt[g]*3; i+=3)
			fscanf_s(fp, "%d %d %d\n", &mshIndicesList[g][i], &mshIndicesList[g][i+1], &mshIndicesList[g][i+2]);

	/*	for(i=0; i<nv[g]; i++)
			printf("[%d] %f %f %f \n", i,
			mshVerticesList[g][i].getX(),  mshVerticesList[g][i].getY(), mshVerticesList[g][i].getZ());

		for(i=0; i<nt[g]*3; i+=3)
			printf("[%d] %d %d %d\n", i, mshIndicesList[g][i], mshIndicesList[g][i+1], mshIndicesList[g][i+2]);*/

		totalVertices += nv[g];
		totalIndices += (nt[g]*3); //number of indices is no. of triangles * 3

		printf("Total Vertices so far  : %d\n", totalVertices);
		printf("Total Indices so far  : %d\n", totalIndices);
	}

	//Merge vertices and indices list into 1
	vertices = new btVector3[totalVertices];
	indices  = new int[totalIndices];

	int vertexOffset = 0, indexOffset = 0;
	for(g=0; g<numGroups; g++){
		//Vertices copy
		for(i=0; i<nv[g]; i++){
			vertices[vertexOffset + i] = mshVerticesList[g][i];
		}

		//Indices copy
		for(i=0; i<nt[g]*3; i++){
			indices[indexOffset + i] = mshIndicesList[g][i] + vertexOffset; //add offset of already added total vertices
		}

		vertexOffset += nv[g]; //important to do this last(see addition above)
		indexOffset += nt[g]*3;
	}

	printf("-----Merge Complete of %d vertices and %d indices-----\n", totalVertices, totalIndices);
/*	for(i=0; i<totalVertices; i++)
			printf("[%d] %f %f %f \n", i, mshVertices[i].getX(),  mshVertices[i].getY(), mshVertices[i].getZ());

	for(i=0; i<totalIndices; i+=3)
		printf("[%d] %d %d %d\n", i, mshIndices[i], mshIndices[i+1], mshIndices[i+2]);

*/
	//Finally make the triangle mesh
	m_indexVertexArrays = new btTriangleIndexVertexArray(totalIndices/3,
			indices,
			indexStride,
			totalVertices,(btScalar*) &vertices[0].x(),vertStride);

	bool useQuantizedAabbCompression = true;
	collShpMSH = new btBvhTriangleMeshShape(m_indexVertexArrays,useQuantizedAabbCompression);

	bump.m_collisionShapes.push_back(collShpMSH);
	btTransform transMSH(btQuaternion(btVector3(0,1,0), (const btScalar)0), offset);

	rbMSH = bump.localCreateRigidBody(0.f, transMSH, collShpMSH);

	//Cleanup
	fclose(fp);

	printf("\n-------Mesh read complete------\n\n");

	delete[] mshVerticesList;
	delete[] mshIndicesList;
	delete nv;
	delete nt;


	return 0;
}


